﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Ink;

namespace RozpoznawanieLiter
{
    public partial class Form1 : Form
    {
        private Microsoft.Ink.InkOverlay collector;

        Line bl;
        Line ml;
        Line ul;
        //bool czyLinie = false;
        List<WłaściwościLitery> zestawUczący;
        Sieć sieć;
        int ilośćEpok;

        public Form1()
        {
            InitializeComponent();

            this.collector = new Microsoft.Ink.InkOverlay(this.panel1);

            collector.Stroke += new InkCollectorStrokeEventHandler(theInkCollector_Stroke);
            collector.CursorInRange += new InkCollectorCursorInRangeEventHandler(kursorWZasięgu);

            this.collector.Enabled = true;

            //Point[] points = { new Point(50, 50), new Point(500, 500) };
            //Stroke dodatkoweMaźnięcie = collector.Ink.CreateStroke(points);
            //collector.Ink.Strokes.Add(dodatkoweMaźnięcie);
            //collector.Ink.DeleteStroke(dodatkoweMaźnięcie);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(this.collector.Ink.Strokes.ToString());            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "";

            foreach (Stroke s in collector.Ink.Strokes)
            {
                richTextBox1.Text += "Maźnięcie: " + s.Id + "\n";

                Point[] ptBezierPoints;
                if (textBox1.Text.Length > 0)
                    ptBezierPoints = s.GetFlattenedBezierPoints(Int32.Parse(textBox1.Text));
                else
                    ptBezierPoints = s.BezierPoints;

                foreach (Point p in ptBezierPoints)
                {
                    richTextBox1.Text += "X: " + p.X + " Y: " + p.Y + "\n";
                }

                richTextBox1.Text += "--------------------\n";
            }

            richTextBox1.Text += "Maźnięć: " + collector.Ink.Strokes.Count;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            collector.Ink.DeleteStrokes();
            Refresh();
        }

        private void pane1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            Strokes theStrokes = collector.Ink.Strokes;

            Point najwyższy = new Point();
            Point najniższy = new Point();
            Point najLewo = new Point();
            Point najPrawo = new Point();

            if (theStrokes.Count > 0)
            {
                najwyższy = theStrokes[0].GetPoints()[0];
                najniższy = theStrokes[0].GetPoints()[0];
                najLewo = theStrokes[0].GetPoints()[0];
                najPrawo = theStrokes[0].GetPoints()[0];
            }

            foreach (Stroke theStroke in theStrokes)
            {
                Point[] ptBezierPoints;
                if (textBox1.Text.Length > 0)
                    ptBezierPoints = theStroke.GetFlattenedBezierPoints(Int32.Parse(textBox1.Text));
                else
                    ptBezierPoints = theStroke.BezierPoints;
                Point[] ptStrokePoints = theStroke.GetPoints();
                collector.Renderer.InkSpaceToPixel(g, ref ptBezierPoints);
                collector.Renderer.InkSpaceToPixel(g, ref ptStrokePoints);

                if (punktyKrzywejToolStripMenuItem.Checked)
                {
                    foreach (Point pt in ptStrokePoints)
                    {
                        g.DrawEllipse(Pens.Magenta, pt.X - 4, pt.Y - 4, 8, 8);
                    }
                }

                if (punktyBezieraToolStripMenuItem.Checked)
                {
                    foreach (Point p in ptBezierPoints)
                    {
                        g.DrawEllipse(Pens.Red, p.X - 4, p.Y - 4, 8, 8);
                    }
                }

                if (wierzchołkiZPunktówBezieraToolStripMenuItem.Checked)
                {
                    int[] theCuspsBezier = theStroke.BezierCusps;
                    foreach (int i in theCuspsBezier)
                    {
                        g.DrawEllipse(Pens.Blue,
                            ptBezierPoints[i].X - 6, ptBezierPoints[i].Y - 6, 12, 12);
                    }
                }

                if (wierzchołkiZPunktówKrzywejToolStripMenuItem.Checked)
                {
                    int[] theCusps = theStroke.PolylineCusps;
                    foreach (int i in theCusps)
                    {
                        g.DrawEllipse(Pens.Brown, ptStrokePoints[i].X - 8, ptStrokePoints[i].Y - 8, 16, 16);
                    }
                }

                if (linieDlaLiteryToolStripMenuItem.Checked)
                {
                    Point pbl1 = bl.BeginPoint;
                    Point pbl2 = bl.EndPoint;
                    collector.Renderer.InkSpaceToPixel(g, ref pbl1);
                    collector.Renderer.InkSpaceToPixel(g, ref pbl2);

                    g.DrawLine(Pens.Violet, pbl1, pbl2);


                    Point pml1 = ml.BeginPoint;
                    Point pml2 = ml.EndPoint;
                    collector.Renderer.InkSpaceToPixel(g, ref pml1);
                    collector.Renderer.InkSpaceToPixel(g, ref pml2);

                    g.DrawLine(Pens.Violet, pml1, pml2);


                    Point pul1 = ul.BeginPoint;
                    Point pul2 = ul.EndPoint;
                    collector.Renderer.InkSpaceToPixel(g, ref pul1);
                    collector.Renderer.InkSpaceToPixel(g, ref pul2);

                    g.DrawLine(Pens.Violet, pul1, pul2);
                }

                if (przecięciaToolStripMenuItem.Checked)
                {
                    float[] własnePrzecięcia = theStroke.SelfIntersections;
                    float[] innePrzecięcia = theStroke.FindIntersections(theStrokes);

                    foreach (float f in własnePrzecięcia)
                    {
                        Point p = LocatePoint(theStroke, f);
                        collector.Renderer.InkSpaceToPixel(g, ref p);

                        g.FillEllipse(Brushes.Red, p.X - 7, p.Y - 7, 14, 14);
                    }

                    foreach (float f in innePrzecięcia)
                    {
                        Point p = LocatePoint(theStroke, f);
                        collector.Renderer.InkSpaceToPixel(g, ref p);

                        g.FillEllipse(Brushes.Pink, p.X - 7, p.Y - 7, 14, 14);
                    }
                }

                foreach (Point p in theStroke.GetPoints())
                {
                    if (p.Y < najwyższy.Y)
                        najwyższy = p;
                    if (p.Y > najniższy.Y)
                        najniższy = p;
                    if (p.X > najPrawo.X)
                        najPrawo = p;
                    if (p.X < najLewo.X)
                        najLewo = p;
                }
            }

            if (ramkaLiteryToolStripMenuItem.Checked)
            {
                collector.Renderer.InkSpaceToPixel(g, ref najwyższy);
                collector.Renderer.InkSpaceToPixel(g, ref najniższy);
                collector.Renderer.InkSpaceToPixel(g, ref najLewo);
                collector.Renderer.InkSpaceToPixel(g, ref najPrawo);

                g.DrawRectangle(Pens.Orange, najLewo.X, najwyższy.Y, najPrawo.X - najLewo.X, najniższy.Y - najwyższy.Y);
            }
        }

        private void theInkCollector_Stroke(object sender, InkCollectorStrokeEventArgs e)
        {
            Refresh();
        }

        private void kursorWZasięgu(object sender, InkCollectorCursorInRangeEventArgs e)
        {
            if (e.Cursor.Inverted)
                collector.EditingMode = InkOverlayEditingMode.Delete;
            else
                collector.EditingMode = InkOverlayEditingMode.Ink;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Refresh();
        }

        private Point LocatePoint(Stroke theStroke, float theFIndex)
        {
            // Get the two nearest points to the point of interest.
            Point[] ptStrokePoints = theStroke.GetPoints((int)Math.Floor(theFIndex), 2);

            // Get fractional part to interpolate the distance between the points.
            float theFraction = theFIndex - (float)Math.Floor(theFIndex);

            int deltaX;
            int deltaY;

            if (ptStrokePoints.Length > 1)
            {
                deltaX = (int)((ptStrokePoints[1].X - ptStrokePoints[0].X) * theFraction);
                deltaY = (int)((ptStrokePoints[1].Y - ptStrokePoints[0].Y) * theFraction);
            }
            else
            {
                deltaX = 0;
                deltaY = 0;
            }

            // Return the interpolated point.
            return new Point(ptStrokePoints[0].X + deltaX, ptStrokePoints[0].Y + deltaY);
        }

        private void zapis(String nazwa)
        {
            byte[] dane = collector.Ink.Save();
            FileStream str = File.Open(nazwa, FileMode.Create);
            str.Write(dane, 0, dane.Length);
            str.Close();
        }

        private void odczyt(String nazwa)
        {
            FileStream str = File.OpenRead(nazwa);
            FileInfo info = new FileInfo(nazwa);
            byte[] dane = new byte[info.Length];
            str.Read(dane, 0, (int)info.Length);
            str.Close();

            Ink nowy = new Ink();
            nowy.Load(dane);
            collector.Enabled = false;
            collector.Ink = nowy;
            collector.Enabled = true;
        }

        private void odczytToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK)
                odczyt(openFileDialog1.FileName);
        }

        private void zapisToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = saveFileDialog1.ShowDialog();

            zapis(saveFileDialog1.FileName);
        }

        private void punktyBezieraToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Refresh();
        }

        private void punktyKrzywejToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Refresh();
        }

        private void wierzchołkiZPunktówBezieraToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Refresh();
        }

        private void wierzchołkiZPunktówKrzywejToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Refresh();
        }

        private void linieDlaLiteryToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Recognizers recs = new Recognizers();
            Recognizer reco = recs.GetDefaultRecognizer(/*0x0C09*/);
            RecognizerContext context = reco.CreateRecognizerContext();
            context.Strokes = collector.Ink.Strokes;
            RecognitionStatus status = RecognitionStatus.NoError;
            RecognitionResult res = context.Recognize(out status);

            bl = res.TopAlternate.Baseline;
            ml = res.TopAlternate.Midline;
            ul = res.TopAlternate.Ascender;

            Refresh();
        }

        private void ramkaLiteryToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Refresh();
        }

        private void przecięciaToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
        {
            Refresh();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            WłaściwościLitery litera = new WłaściwościLitery('a');

            litera.znajdźRatio(collector.Ink.Strokes);
            litera.znajdźLinie(collector.Ink.Strokes);
            litera.znajdźSzerokośćDoWielkościLinii(collector.Ink.Strokes);
            litera.znajdźWysokośćDoWielkościLinii(collector.Ink.Strokes);
            litera.znajdźŚredniąSzerokośćLitery(collector);
            litera.znajdźŚredniąWysokośćLitery(collector);
            litera.znajdźNajwyższyPunktDoGórnejLini(collector.Ink.Strokes);
            litera.znajdźNajniższyPunktDoDolnejLini(collector.Ink.Strokes);
            litera.znajdźIlośćPrzecięćZLiniamiPoziomymi(collector);
            //litera.znajdźIlośćPrzecięć(collector);
            //litera.znajdźIlośćMaźnięć(collector.Ink.Strokes);
            litera.znajdźIlośćPrzerwWPionowymHistogramie(collector);
            litera.znajdźPołożejnieNaj(collector.Ink.Strokes);

            richTextBox1.Text = "";

            richTextBox1.Text += "Ratio: " + litera.Ratio + "\n";
            richTextBox1.Text += "Szerokość do wysokości linii:" + litera.SzerokośćDoWielkościLinii + "\n";
            richTextBox1.Text += "Wysokość do wysokości linii: " + litera.WysokośćDoWielkościLinii + "\n";
            richTextBox1.Text += "Średnia szerokość litery: " + litera.ŚredniaSzerokośćLitery + "\n";
            richTextBox1.Text += "Średnia wysokość litery: " + litera.ŚredniaWysokośćLitery + "\n";
            richTextBox1.Text += "Najwyższy punkt do górnej linii: " + litera.NajwyższyPunktDoGórnejLinii + "\n";
            richTextBox1.Text += "Najniższy punkt do dolnej linii: " + litera.NajniższyPunktDoDolnejLinii + "\n";
            richTextBox1.Text += "Ilość przecięć z liniami poziomymi: " + litera.IlośćPrzecięćZLiniamiPoziomymi + "\n";
            //richTextBox1.Text += "Ilość przecięć: " + litera.IlośćPrzecięć + "\n";
            richTextBox1.Text += "Ilość przerw w pionowych histogramie: " + litera.IlośćPrzerwWPionowymHistogramie + "\n";
            //richTextBox1.Text += "Ilość maźnięć: " + litera.IlośćMaźnięć + "\n";
            richTextBox1.Text += "Położenie najwyższego: " + litera.PołożenieNajwyższego + "\n";
            richTextBox1.Text += "Położenie najniższego: " + litera.PołożenieNajniższego + "\n";
            richTextBox1.Text += "Położenie naj-lewo: " + litera.PołożenieNajLewo + "\n";
            richTextBox1.Text += "Położenie naj-prawo: " + litera.PołożenieNajPrawo + "\n";
        }

        private double[] wyjścieDlaLiterki(char litera)
        {
            switch (litera)
            {
                case 'a':
                    return new double[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ą':
                    return new double[] { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'b':
                    return new double[] { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'c':
                    return new double[] { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ć':
                    return new double[] { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'd':
                    return new double[] { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'e':
                    return new double[] { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ę':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'f':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'g':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'h':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'i':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'j':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'k':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'l':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ł':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'm':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'n':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ń':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'o':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ó':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'p':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'r':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 's':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
                case 'ś':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
                case 't':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
                case 'u':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 };
                case 'w':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 };
                case 'y':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
                case 'z':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
                case 'ź':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
                case 'ż':
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
                default:
                    return new double[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            }
        }

        private char literkaDlaWyjścia(int pozycja)
        {
            switch (pozycja)
            {
                case 0:
                    return 'a';
                case 1:
                    return 'ą';
                case 2:
                    return 'b';
                case 3:
                    return 'c';
                case 4:
                    return 'ć';
                case 5:
                    return 'd';
                case 6:
                    return 'e';
                case 7:
                    return 'ę';
                case 8:
                    return 'f';
                case 9:
                    return 'g';
                case 10:
                    return 'h';
                case 11:
                    return 'i';
                case 12:
                    return 'j';
                case 13:
                    return 'k';
                case 14:
                    return 'l';
                case 15:
                    return 'ł';
                case 16:
                    return 'm';
                case 17:
                    return 'n';
                case 18:
                    return 'ń';
                case 19:
                    return 'o';
                case 20:
                    return 'ó';
                case 21:
                    return 'p';
                case 22:
                    return 'r';
                case 23:
                    return 's';
                case 24:
                    return 'ś';
                case 25:
                    return 't';
                case 26:
                    return 'u';
                case 27:
                    return 'w';
                case 28:
                    return 'y';
                case 29:
                    return 'z';
                case 30:
                    return 'ź';
                case 31:
                    return 'ż';
                default:
                    return 'a';
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            if (zestawUczący == null)
                MessageBox.Show("Brak wczytanego zestawu uczącego!");
            else
            {
                ilośćEpok = 0;
                //int licznik = 0;
                Random random = new Random();

                string[] win = textBox5.Text.Split(new char[1] { ',' });

                int[] warstwyINeurony = new int[win.Length];
                for (int i = 0; i < win.Length; i++)
                    warstwyINeurony[i] = Int32.Parse(win[i]);

                sieć = new Sieć(warstwyINeurony, Double.Parse(textBox3.Text), Double.Parse(textBox4.Text));

                int ilośćWzorców = zestawUczący.Count;

                double[] oczekiwaneWyjście = new double[32];

                double błądEpoki;

                while (ilośćEpok < 50000)
                {
                    List<WłaściwościLitery> tymczasowyZestawUczący = new List<WłaściwościLitery>(zestawUczący);
                    //bool błądSpełniony = false;

                    błądEpoki = 0;

                    for (int i = 0; i < ilośćWzorców; i++)
                    {
                        int któraAktualna = random.Next(0, tymczasowyZestawUczący.Count);
                        WłaściwościLitery aktualnaLitera = tymczasowyZestawUczący[któraAktualna];

                        char jakaLitera = aktualnaLitera.Litera;
                        double[] wejście = new double[] { aktualnaLitera.Ratio, aktualnaLitera.SzerokośćDoWielkościLinii, aktualnaLitera.WysokośćDoWielkościLinii, aktualnaLitera.ŚredniaSzerokośćLitery, aktualnaLitera.ŚredniaWysokośćLitery, aktualnaLitera.NajwyższyPunktDoGórnejLinii, aktualnaLitera.NajniższyPunktDoDolnejLinii, aktualnaLitera.IlośćPrzecięćZLiniamiPoziomymi, aktualnaLitera.IlośćPrzerwWPionowymHistogramie/*, aktualnaLitera.IlośćMaźnięć*/, aktualnaLitera.PołożenieNajwyższego, aktualnaLitera.PołożenieNajniższego, aktualnaLitera.PołożenieNajLewo, aktualnaLitera.PołożenieNajPrawo };
                        oczekiwaneWyjście = wyjścieDlaLiterki(jakaLitera);

                        tymczasowyZestawUczący.RemoveAt(któraAktualna);

                        sieć.propagacja(wejście, oczekiwaneWyjście);

                        błądEpoki += sieć.mse(oczekiwaneWyjście);

                        //if (sieć.mse(oczekiwaneWyjście) < Double.Parse(textBox6.Text))
                        //{
                        //    błądSpełniony = true;
                        //    break;
                        //}
                    }

                    ilośćEpok++;

                    błądEpoki /= ilośćWzorców;
                    //richTextBox1.Text = "";
                    richTextBox1.AppendText("Błąd: " + błądEpoki + " Epok: " + ilośćEpok + "\n");
                    //richTextBox1.ScrollToCaret();

                    if (błądEpoki < Double.Parse(textBox6.Text))
                        break;
                }
            }
            //if (collector.Ink.Strokes.Count == 0)
            //    MessageBox.Show("Nic nie jest narysowane!");
            //else if (textBox2.Text.Length == 0)
            //    MessageBox.Show("Co to za litera?");
            //else
            //{
            //    WłaściwościLitery litera = new WłaściwościLitery(textBox2.Text.ElementAt(0));

            //    litera.znajdźRatio(collector.Ink.Strokes);
            //    litera.znajdźLinie(collector.Ink.Strokes);
            //    litera.znajdźSzerokośćDoWielkościLinii(collector.Ink.Strokes);
            //    litera.znajdźWysokośćDoWielkościLinii(collector.Ink.Strokes);
            //    litera.znajdźŚredniąSzerokośćLitery(collector);
            //    litera.znajdźŚredniąWysokośćLitery(collector);
            //    litera.znajdźNajwyższyPunktDoGórnejLini(collector.Ink.Strokes);
            //    litera.znajdźNajniższyPunktDoDolnejLini(collector.Ink.Strokes);
            //    litera.znajdźIlośćPrzecięćZLiniamiPoziomymi(collector);
            //    litera.znajdźIlośćPrzecięć(collector);
            //    litera.znajdźIlośćMaźnięć(collector.Ink.Strokes);
            //    litera.znajdźIlośćPrzerwWPionowymHistogramie(collector);

            //    richTextBox1.Text = "";

            //    richTextBox1.Text += "Ratio: " + litera.Ratio + "\n";
            //    richTextBox1.Text += "Szerokość do wysokości linii:" + litera.SzerokośćDoWielkościLinii + "\n";
            //    richTextBox1.Text += "Wysokość do wysokości linii: " + litera.WysokośćDoWielkościLinii + "\n";
            //    richTextBox1.Text += "Średnia szerokość litery: " + litera.ŚredniaSzerokośćLitery + "\n";
            //    richTextBox1.Text += "Średnia wysokość litery: " + litera.ŚredniaWysokośćLitery + "\n";
            //    richTextBox1.Text += "Najwyższy punkt do górnej linii: " + litera.NajwyższyPunktDoGórnejLinii + "\n";
            //    richTextBox1.Text += "Najniższy punkt do dolnej linii: " + litera.NajniższyPunktDoDolnejLinii + "\n";
            //    richTextBox1.Text += "Ilość przecięć z liniami poziomymi: " + litera.IlośćPrzecięćZLiniamiPoziomymi + "\n";
            //    richTextBox1.Text += "Ilość przecięć: " + litera.IlośćPrzecięć + "\n";
            //    richTextBox1.Text += "Ilość przerw w pionowych histogramie: " + litera.IlośćPrzerwWPionowymHistogramie + "\n";
            //    richTextBox1.Text += "Ilość maźnięć: " + litera.IlośćMaźnięć + "\n";
            //}
        }

        private void ącyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            zestawUczący = new List<WłaściwościLitery>();

            richTextBox1.Text = "";
            richTextBox1.Text = "Stworzono nowy zestaw uczący\n";
        }

        private void dodajFolToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = folderBrowserDialog1.ShowDialog();

            if (result == DialogResult.OK)
            {
                DirectoryInfo folder = new DirectoryInfo(folderBrowserDialog1.SelectedPath);

                FileInfo[] pliki = folder.GetFiles();
                string[] plikiString = Directory.GetFiles(folderBrowserDialog1.SelectedPath);

                for (int i = 0; i < pliki.Length; i++)
                {
                    odczyt(plikiString[i]);

                    WłaściwościLitery litera = new WłaściwościLitery(pliki[i].Name[0]);

                    litera.znajdźRatio(collector.Ink.Strokes);
                    litera.znajdźLinie(collector.Ink.Strokes);
                    litera.znajdźSzerokośćDoWielkościLinii(collector.Ink.Strokes);
                    litera.znajdźWysokośćDoWielkościLinii(collector.Ink.Strokes);
                    litera.znajdźŚredniąSzerokośćLitery(collector);
                    litera.znajdźŚredniąWysokośćLitery(collector);
                    litera.znajdźNajwyższyPunktDoGórnejLini(collector.Ink.Strokes);
                    litera.znajdźNajniższyPunktDoDolnejLini(collector.Ink.Strokes);
                    litera.znajdźIlośćPrzecięćZLiniamiPoziomymi(collector);
                    //litera.znajdźIlośćPrzecięć(collector);
                    //litera.znajdźIlośćMaźnięć(collector.Ink.Strokes);
                    litera.znajdźIlośćPrzerwWPionowymHistogramie(collector);
                    litera.znajdźPołożejnieNaj(collector.Ink.Strokes);

                    zestawUczący.Add(litera);
                }
            }
        }

        private void zapisZestawUczącyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = saveFileDialog1.ShowDialog();

            StreamWriter sw = new StreamWriter(saveFileDialog1.FileName);

            foreach (WłaściwościLitery litera in zestawUczący)
            {
                sw.WriteLine(litera.Litera);
                sw.WriteLine(litera.Ratio);
                sw.WriteLine(litera.SzerokośćDoWielkościLinii);
                sw.WriteLine(litera.WysokośćDoWielkościLinii);
                sw.WriteLine(litera.ŚredniaSzerokośćLitery);
                sw.WriteLine(litera.ŚredniaWysokośćLitery);
                sw.WriteLine(litera.NajwyższyPunktDoGórnejLinii);
                sw.WriteLine(litera.NajniższyPunktDoDolnejLinii);
                sw.WriteLine(litera.IlośćPrzecięćZLiniamiPoziomymi);
                //sw.WriteLine(litera.IlośćPrzecięć);
                sw.WriteLine(litera.IlośćPrzerwWPionowymHistogramie);
                //sw.WriteLine(litera.IlośćMaźnięć);
                sw.WriteLine(litera.PołożenieNajwyższego);
                sw.WriteLine(litera.PołożenieNajniższego);
                sw.WriteLine(litera.PołożenieNajLewo);
                sw.WriteLine(litera.PołożenieNajPrawo);
            }

            sw.Close();
        }

        private void odczytajZestawUczącyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = openFileDialog1.ShowDialog();

            if (result == DialogResult.OK)
            {
                StreamReader sr = new StreamReader(openFileDialog1.FileName);

                zestawUczący = new List<WłaściwościLitery>();

                string linia = "start";
                linia = sr.ReadLine();
                //sr.DiscardBufferedData();
                //sr.BaseStream.Seek(0, SeekOrigin.Begin);

                while (linia != null)
                {
                    WłaściwościLitery litera = new WłaściwościLitery(linia[0]);

                    linia = sr.ReadLine();
                    litera.Ratio = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.SzerokośćDoWielkościLinii = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.WysokośćDoWielkościLinii = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.ŚredniaSzerokośćLitery = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.ŚredniaWysokośćLitery = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.NajwyższyPunktDoGórnejLinii = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.NajniższyPunktDoDolnejLinii = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.IlośćPrzecięćZLiniamiPoziomymi = Double.Parse(linia);

                    //linia = sr.ReadLine();
                    //litera.IlośćPrzecięć = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.IlośćPrzerwWPionowymHistogramie = Double.Parse(linia);

                    //linia = sr.ReadLine();
                    //litera.IlośćMaźnięć = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.PołożenieNajwyższego = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.PołożenieNajniższego = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.PołożenieNajLewo = Double.Parse(linia);

                    linia = sr.ReadLine();
                    litera.PołożenieNajPrawo = Double.Parse(linia);

                    linia = sr.ReadLine();

                    zestawUczący.Add(litera);
                }

                sr.Close();
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            if (collector.Ink.Strokes.Count == 0)
                MessageBox.Show("Nic nie jest narysowane!");
            else
            {
                WłaściwościLitery litera = new WłaściwościLitery('?');

                litera.znajdźRatio(collector.Ink.Strokes);
                litera.znajdźLinie(collector.Ink.Strokes);
                litera.znajdźSzerokośćDoWielkościLinii(collector.Ink.Strokes);
                litera.znajdźWysokośćDoWielkościLinii(collector.Ink.Strokes);
                litera.znajdźŚredniąSzerokośćLitery(collector);
                litera.znajdźŚredniąWysokośćLitery(collector);
                litera.znajdźNajwyższyPunktDoGórnejLini(collector.Ink.Strokes);
                litera.znajdźNajniższyPunktDoDolnejLini(collector.Ink.Strokes);
                litera.znajdźIlośćPrzecięćZLiniamiPoziomymi(collector);
                //litera.znajdźIlośćPrzecięć(collector);
                //litera.znajdźIlośćMaźnięć(collector.Ink.Strokes);
                litera.znajdźIlośćPrzerwWPionowymHistogramie(collector);
                litera.znajdźPołożejnieNaj(collector.Ink.Strokes);

                double[] wejście = new double[] { litera.Ratio, litera.SzerokośćDoWielkościLinii, litera.WysokośćDoWielkościLinii, litera.ŚredniaSzerokośćLitery, litera.ŚredniaWysokośćLitery, litera.NajwyższyPunktDoGórnejLinii, litera.NajniższyPunktDoDolnejLinii, litera.IlośćPrzecięćZLiniamiPoziomymi, litera.IlośćPrzerwWPionowymHistogramie/*, litera.IlośćMaźnięć*/, litera.PołożenieNajwyższego, litera.PołożenieNajniższego, litera.PołożenieNajLewo, litera.PołożenieNajPrawo };

                sieć.wyliczanie(wejście);

                double[] wyjścia = sieć.dajWyjscia();

                //Array.Sort(wyjścia);

                richTextBox1.Text = "";

                List<Litera> litery = new List<Litera>();

                for (int i = 0; i < 32; i++)
                {
                    richTextBox1.Text += literkaDlaWyjścia(i) + ": " + wyjścia[i].ToString("0.0000000") + "\n";
                    litery.Add(new Litera(wyjścia[i], literkaDlaWyjścia(i)));
                }

                char pierwsza = litery.Max().JakaLitera;
                litery.Remove(litery.Max());
                char druga = litery.Max().JakaLitera;
                litery.Remove(litery.Max());
                char trzecia = litery.Max().JakaLitera;
                litery.Remove(litery.Max());
                char czwarta = litery.Max().JakaLitera;
                litery.Remove(litery.Max());

                MessageBox.Show("Najprawdopodobniej jest to litera: " + pierwsza + "\nEwentualnie: " + druga + ", " + trzecia + ", " + czwarta);
            }
        }
    }

    class Litera : IComparable<Litera>
    {
        private double wartość;
        private char litera;

        public Litera(double w, char l)
        {
            wartość = w;
            litera = l;
        }

        public double Wartość
        {
            get
            {
                return wartość;
            }
        }

        public char JakaLitera
        {
            get
            {
                return litera;
            }
        }

        int IComparable<Litera>.CompareTo(Litera inna)
        {
            if (inna.wartość > this.wartość)
                return -1;
            else if (inna.wartość == this.wartość)
                return 0;
            else
                return 1;
        }
    }
}
